package com.apestech.framework.xml.condition.modul;

import com.apestech.api.tables.modul.SeqField;
import com.apestech.framework.db.SqlSession;
import com.apestech.framework.json.JSONArray;
import com.apestech.framework.json.JSONObject;
import com.apestech.framework.sql.SqlUtil;
import com.apestech.framework.util.LocalVariable;
import com.apestech.framework.xml.plugin.modul.Model;
import com.apestech.framework.xml.plugin.modul.SysCondition;
import com.apestech.framework.xml.table.modul.Tables;
import java.util.ArrayList;

/**
 * @author hup
 * @create 2019-01-23-10:57
 */
public class Condition extends SqlUtil{
    private String id;
    private String name;
    private String controlType="0";
    private int expiring=365;
    private ArrayList<Dimension> dimension;
    private Control control;
    private ArrayList<Tables> tables;
    private JSONObject tablesIndex;
    private boolean update=false;
    private JSONArray masterlist;
    private JSONArray cuslist=new JSONArray();
    private JSONArray controllist;
    private JSONObject controlmap;
    private SysCondition sysCondition;
    private Model sysModel;
    private SqlSession session;
    private String theme;
    private String sysModelId="baseSysConditon";
    private JSONObject dimensionField=new JSONObject();
    private TableKey tableKey;
    private JSONObject allField=new JSONObject();
    private ArrayList<SeqField> seqlist;
    private boolean invalid;
    private SeqField seq;
    private JSONObject mapping;
    private JSONObject memoJSON;
    private JSONObject formJSON;
    private String tag;

    public Condition(){
    }

    public Condition(Condition condition){
        id=condition.id;
        name=condition.name;
        tag=condition.tag;
        controlType=condition.controlType;
        expiring=condition.expiring;
        dimension=condition.dimension;
        control=condition.control;
        tables=condition.tables;
        tablesIndex=condition.tablesIndex;
        update=condition.update;
        masterlist=condition.masterlist;
        cuslist=condition.cuslist;
        controllist=condition.controllist;
        controlmap=condition.controlmap;
        sysCondition=condition.sysCondition;
        sysModel=condition.sysModel;
        session=condition.session;
        theme=condition.theme;
        sysModelId=condition.theme;
        dimensionField=condition.dimensionField;
        tableKey=condition.tableKey;
        allField=condition.allField;
        seqlist=condition.seqlist;
        invalid=condition.invalid;
        seq=condition.seq;
        mapping=condition.mapping;
        memoJSON=condition.memoJSON;
        formJSON=condition.formJSON;
    }

    public void setCondition(JSONObject map, SqlSession session) throws Exception {
        this.id=map.getString("id");
        this.name=map.getString("name");
        this.controlType=map.getString("controlType");
        if(map.get("expiring")!=null){
            this.expiring=map.getIntValue("expiring");
        }
        this.invalid="true".equals(map.getString("invalid"));
        this.session=session;
        sysCondition=LocalVariable.getConfig().getSysCondition(this.session);
        tableKey=new TableKey(sysCondition.getTableName().getName(), sysCondition.getTableName().getKeyValue(), id);
    }

    public void setDimension(ArrayList<Dimension> dimension) {
        this.dimension = dimension;
        if(this.dimension!=null && this.dimension.size()>0){
            session=this.dimension.get(0).getSession();
            theme=session.getTheme();
            if(theme!=null) theme=theme+".";
            else theme="";
            theme=theme.toLowerCase();
        }
    }

    public void setControl(Control control) {
        this.control = control;
        if(this.control!=null) update=this.control.isUpdate();
    }

    public Control getControl() {
        return control;
    }

    public JSONObject getFormJSON() {
        return formJSON;
    }

    public void setFormJSON(JSONObject formJSON) {
        this.formJSON = formJSON;
    }

    public void setMapping(JSONObject map){
        mapping=map;
    }

    public JSONObject getMapping() {
        return mapping;
    }

    public String getId() {
        return id;
    }

    public ArrayList<Field> getControlFields() {
        if(control==null) return null;
        return control.getFields();
    }

    public String getName() {
        return name;
    }

    public void setCuslist(JSONObject map){
        map.put("id", map.getString("field"));
        map.put("comment", map.getString("name"));
        cuslist.add(map);
    }

    public boolean isInvalid() {
        return invalid;
    }

    public ArrayList<Tables> getTables() throws Exception {
        if(theme==null) {
            theme=session.getTheme();
            if(theme!=null){
                theme=theme+".";
            }
        }
        if(tables==null){
            tables=new ArrayList<Tables>();
            tablesIndex=new JSONObject();
            sysModel=LocalVariable.getConfig().getModel();
            setMasterList();
            getControlFieldList();
            int len=dimension.size();
            for(int i=0; i<len; i++){
                Tables table=new Tables();
                dimension.get(i).getFieldlist();
                dimensionField.putAll(dimension.get(i).getFielddir());
                String sid=tableKey.getTabName(dimension.get(i).getId());
                table.setId(sid);
                addMasterTable(sid, table, i);
                addExecField(sid, table, addItemTable(sid, table, i), i);
                table.expain(session);
                table.setTimeField(session.getSpecialField().getTimestamp());
                table.setIndex(tables.size());
                SeqField seqField=this.getSeq();
                if(seqField==null){
                    String prefix=getTableKey().getPrefix();
                    String suffix=getTableKey().getSuffix();
                    seqField=new SeqField();
                    seqField.setPadding(6);
                    seqField.setPrefix(prefix);
                    if(suffix!=null) seqField.setSuffix(suffix);
                }
                seqField.setTableId(table.getMasterTableId());
                seqField.setTableName(table.getTabComment(seqField.getTableId()));
                table.setSeq(seqField);
                tables.add(table);
                tablesIndex.put(sid, tables.size()-1);
            }
            initTable();
        }
        return tables;
    }

    public Tables getTablesById(String id) throws Exception {
        Integer inx=tablesIndex.getInteger(id);
        if(inx==null) return null;
        return tables.get(inx);
    }

    public boolean isUpdate() {
        return update;
    }

    private JSONArray addItemTable(String id, Tables table, int inx) throws Exception {
        table.addTabInfo(id+"_ITEM", getTabInfo(id+"_ITEM", name+"明细"));
        table.addMasterTab(id+"_ITEM", id+"_ITEM", id,id);
        table.addTabInfo(id+"_EXEC", getTabInfo(id+"_EXEC", name+"执行"));
        table.addMasterTab(id+"_EXEC", id+"_EXEC", "2","2");

        JSONArray flist= new JSONArray();
        JSONArray alist=dimension.get(inx).getFieldlist();
        String master=dimension.get(inx).getMaster();
        if(master!=null){
            int len=alist.size();
            for(int i=0; i<len; i++){
                JSONObject f=alist.get(i);
                if((","+master+",").indexOf(","+f.getString("id")+",")<0){
                    flist.add(f);
                }
            }
        } else {
            flist.addAll(alist);
        }
        flist.addAll(controllist);
        int len=flist.size();
        for(int i=0; i<len; i++){
            table.addField(id+"_ITEM", flist.get(i));
            allField.put(flist.get(i).getString("id"), flist.get(i));
        }
        return flist;
    }

    private void getControlFieldList() throws Exception {
        if(controllist==null){
            controllist=new JSONArray();
            controlmap=new JSONObject();
            ArrayList<Field> list=control.getFields();
            boolean lower=control.isLower();
            boolean upper=control.isUpper();
            int len=list.size();
            for(int i=0; i<len; i++){
                Field f=list.get(i);
                String fid=f.getId();
                fid=theme+fid;
                String fname=f.getName();
                String field=f.getField();
                JSONObject map=sysCondition.getControlField(fid);
                Integer range=null;
                if(control.getRange()!=null){
                    if(f.isLadder() ) range=control.getRange();
                    if(f.isResult()){
                        if((lower&&!upper)||(!lower&&upper)) range=control.getRange();
                        else if(lower&&upper) range=control.getRange()+1;
                        else range=control.getRange()-1;
                    }
                    if(range!=null && f.getCount()!=null) throw new Exception("参与阶梯类型计算的字段，不允许配置count属性!");
                }
                if(range==null || range<1) range=1;
                if(f.getCount()!=null){
                    if(f.getCount()<1) range=1;
                    else range=f.getCount();
                }
                for(int j=0; j<range; j++){
                    JSONObject m= new JSONObject();
                    if(map!=null) m.putAll(map);
                    if(field==null) field=f.getId();
                    if(fname==null){
                        if(map!=null) fname=map.getString("comment");
                        else fname=field;
                    }
                    if(range==1){
                        m.put("id", field);
                        m.put("comment", fname);
                    }
                    else{
                        m.put("id", field+"_"+(j+1));
                        m.put("comment", fname+"_"+(j+1));
                    }
                    if(map==null){
                        if(f.getType()==null) throw new Exception("没有指定id属性字段，必须要配置type属性！");
                        if(f.getDefaultValue()!=null) m.put("defaultValue", f.getDefaultValue());
                        m.put("type", f.getType());
                    }
                    controllist.add(m);
                    list.get(i).setType(m.getString("type"));
                    controlmap.put(m.getString("id"), controllist.size()-1);
                    allField.put(m.getString("id"), m);
                }
            }
            if(memoJSON!=null){
                controllist.add(memoJSON);
            }
        }
    }

    private void addExecField(String id, Tables table, JSONArray list, int inx) throws Exception {
        String sid=theme+sysCondition.getModel().getControl();
        JSONArray flist= sysModel.getModelFields(sid);
        JSONArray tlist=new JSONArray();
        int len=flist.size();
        for(int i=0; i<len; i++){
            JSONObject m=new JSONObject();
            m.putAll(flist.get(i));
            if(i==0) m.remove("isKey");
            tlist.add(m);
        }
        String master=dimension.get(inx).getMaster();
        if(master!=null){
            JSONArray alist=dimension.get(inx).getFieldlist();
            len=alist.size();
            for(int i=0; i<len; i++){
                JSONObject m=alist.get(i);
                String sfield=m.getString("id");
                if((","+master+",").indexOf(","+sfield+",")>=0){
                    m.put("isKey", "true");
                    tlist.add(m);
                }
            }
        }
        tlist.addAll(list);
        tlist.addAll(sysModel.getModelFields(theme+"base"));
        len=tlist.size();
        boolean flag=false;
        for(int i=0; i<len; i++){
            JSONObject f=new JSONObject(tlist.get(i));
            String sfield=f.getString("id");
            if(session.getSpecialField().getMemo().equals(sfield)){
                if(flag){
                    continue;
                } else {
                    flag=true;
                }
            }
            String startDate=session.getSpecialField().getStartDate();
            String endDate=session.getSpecialField().getEndDate();
            if(startDate.equals(sfield) || endDate.equals(sfield) ){
                f.put("isKey", "true");
            }
            table.addField(id+"_EXEC",f);
        }
    }

    private void addMasterTable(String id, Tables table, int inx) throws Exception {
        table.addTabInfo(id, getTabInfo(id, name));
        table.addMasterTab(id, id, "1","1");
        String master=dimension.get(inx).getMaster();
        if(master!=null){
            JSONArray alist=dimension.get(inx).getFieldlist();
            int len=alist.size();
            for(int i=0; i<len; i++){
                JSONObject m=alist.get(i);
                if((","+master+",").indexOf(","+m.getString("id")+",")>=0){
                    m.remove("isKey");
                    table.addField(id, m);
                }
            }
        }
        int len=masterlist.size();
        for(int i=0; i<len; i++){
            table.addField(id, masterlist.get(i));
        }
        len=cuslist.size();
        for(int i=0; i<len; i++){
            table.addField(id, cuslist.get(i));
        }
    }

    private void setMasterList() throws Exception {
        if(masterlist==null){
            masterlist=new JSONArray();
            String sid=theme+sysModelId;
            if(sysModel.getModel().get(sid)==null){
                String bill=theme+sysCondition.getModel().getBill();
                String con=theme+sysCondition.getModel().getControl();
                String ext=theme+sysCondition.getModel().getExtend();
                sysModel.addList(sid,con);
                sysModel.addList(sid,bill);
                sysModel.addList(sid,ext);
            }
            masterlist.addAll(sysModel.getModelFields(sid));
            int len=masterlist.size();
            for(int i=0; i<len; i++){
                sid=masterlist.get(i).getString("id");
                if(sid.equals(session.getSpecialField().getMemo())){
                    memoJSON=masterlist.get(i);
                }
                allField.put(sid, masterlist.get(i));
            }
        }
    }

    private JSONObject getTabInfo(String tabName, String tabComment){
        JSONObject m=new JSONObject();
        m.put("tabName", tabName);
        m.put("tabComment", tabComment);
        return m;
    }

    public SysCondition getSysCondition() {
        return sysCondition;
    }

    public ArrayList<Dimension> getDimension() {
        return dimension;
    }

    public Dimension getDimensionById(String dimensionId) {
        Dimension d=null;
        int len=dimension.size();
        for(int i=0; i<len; i++){
            if(dimension.get(i).getId().equals(dimensionId)){
                d=dimension.get(i);
                break;
            }
        }
        return d;
    }

    public JSONObject getDimensionField() {
        return dimensionField;
    }

    public TableKey getTableKey() {
        return tableKey;
    }

    public JSONObject getDimensionCondtionParam(String dimensionId, JSONObject input){
        JSONObject param=new JSONObject();
        int len=dimension.size();
        for(int i=0; i<len; i++){
            Dimension d=dimension.get(i);
            if(d.getId().equals(dimensionId)){
                ArrayList<Field> f=d.getFields();
                int flen=f.size();
                for(int j=0; j<flen; j++){
                    String key=f.get(j).getId();
                    param.put(key, input.get(key));
                }
                break;
            }
        }
        return param;
    }

    public String getDimensionCondtionWhere(String dimensionId){
        String sql="";
        int len=dimension.size();
        for(int i=0; i<len; i++){
            Dimension d=dimension.get(i);
            if(d.getId().equals(dimensionId)){
                ArrayList<Field> f=d.getFields();
                int flen=f.size();
                for(int j=0; j<flen; j++){
                    String key=f.get(j).getId();
                    sql=sql+" AND "+key+"=#{"+key+"}";
                }
                break;
            }
        }
        return sql;
    }

    public class ExecTableData {
        private String tableName;
        private String dimensionId;
        private JSONArray list;
        public ExecTableData(String tableName, String dimensionId, JSONArray list){
            this.tableName=tableName;
            this.dimensionId=dimensionId;
            this.list=list;
        }

        public String getTableName() {
            return tableName;
        }

        public String getDimensionId() {
            return dimensionId;
        }

        public JSONArray getList() {
            return list;
        }
    }

    public ExecTableData getExecTableData(String idValue, JSONObject input) throws Exception {
        String execTable=tableKey.getTableFromValue(idValue)+"_EXEC";
        String dimensionId=tableKey.getDimensionId();
        JSONObject param=getDimensionCondtionParam(dimensionId, input);
        param.put("ID", idValue);
        String sql="SELECT * FROM "+execTable+" WHERE ID=#{ID} ";
        JSONArray list=session.getForJSON().query(sql, param);
        return new ExecTableData(execTable, dimensionId, list);
    }

    public ExecTable getExecTable(String idValue){
        String tab=tableKey.getTableFromValue(idValue)+"_EXEC";
        String where=getDimensionCondtionWhere(tableKey.getDimensionId());
        return new ExecTable(tab, where);
    }

    public JSONObject getControlField(String field) throws Exception {
        if(controlmap==null) return null;
        Integer inx=controlmap.getInteger(field);
        if(inx==null) return null;
        return controllist.get(inx);
    }

    public JSONObject getAllField() {
        return allField;
    }

    public void initTable() throws Exception {
        if(seqlist==null){
            seqlist=new ArrayList<SeqField>();
            int len=tables.size();
            for(int i=0; i<len; i++){
                String tableName=tables.get(i).getMasterTableId();
//                if(!session.tableExists(tableName)){
//                    ConditionExec exec=new ConditionExec(session, id);
//                    exec.createTable();
//                } else {
                String prefix=getTableKey().getPrefix();
                String suffix=getTableKey().getSuffix();
                SeqField seqField=new SeqField();
                seqField.setPadding(6);
                seqField.setPrefix(prefix);
                if(suffix!=null) seqField.setSuffix(suffix);
                seqField.setTableId(tableName);
                seqField.setTableName(session.getForJSON().getTabComment(tableName));
                //tables.get(i).getTable(tableName).setSeqField(seqField);
                seqlist.add(seqField);
//                }
            }
        }
    }

    public ArrayList<SeqField> getSeqlist() {
        return seqlist;
    }

    public void setSeq(JSONObject map) throws Exception {
        if(seq==null){
            seq=new SeqField();
        }
        map.put("idField", session.getSpecialField().getConditionId());
        seq.setField(map);
    }

    public SeqField getSeq() {
        return seq;
    }

    public SqlSession getSession() {
        return session;
    }

    public void setSession(SqlSession session) {
        this.session = session;
    }

    public String getControlType() {
        return controlType;
    }

    public int getExpiring() {
        return expiring;
    }

    public String getTag() {
        return tag;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }
}
